home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Maclife 42
/
MACLIFE42.ISO.7z
/
MACLIFE42.ISO
/
FreeWare200
/
圧縮伸張⁄コード
/
MacGzip
/
MacGzip 1.1.2 Source.sea
/
MacGzip 1.1.2 Source
/
Mac
/
GetFolder.c
< prev
next >
Wrap
Text File
|
1997-04-01
|
9KB
|
369 lines
/* StandardGetFolder example
Steve Falkenburg -- MacDTS
This sample uses the new System 7 CustomGetFile routine
to provide a StandardGetFolder call to be used by applications
when the user needs to select a folder instead of a file.
It's written in Think C, but should work in MPW if a few #include
files are added.
The style of the dialog box is taken from the Human Interface note
on folder selection.
SJF 5/2/92 added check for empty filename and call to MakeFSSpec
SJF 5/2/92 added check for refcon in filter and hook routines
SJF 10/30/91 original coding
SPD 8/14/95 UPP and minor changes
*/
#include <Folders.h>
#include <Aliases.h>
#include "GzPStrings.h"
#if GENERATINGCFM || USESROUTINEDESCRIPTORS
# define CreateRoutineDescriptor(info, proc) ¥
RoutineDescriptor g##proc##RD = BUILD_ROUTINE_DESCRIPTOR(info, proc)
# define GetRoutineAddress(proc) (&g##proc##RD)
#else
# define GetRoutineAddress(proc) proc
#endif
/* prototypes */
Boolean SFGetFolder(FSSpec *fSpec);
static void InitStuff(void);
static pascal short MyDlgHook(short item,DialogPtr theDlg,Ptr userData);
static pascal Boolean MyModalFilter(DialogPtr theDlg,EventRecord *ev,short *itemHit,Ptr myData);
static void HitButton(DialogPtr theDlg,short item);
static pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr);
static void SetSelectButtonName(StringPtr selName,Boolean hilited,DialogPtr theDlg);
static Boolean SameFile(FSSpec *file1,FSSpec *file2);
static Boolean GetFSSpecPartialName(FSSpec *file,StringPtr fName);
static OSErr GetDeskFolderSpec(FSSpec *fSpec,short vRefNum);
static OSErr MakeCanonFSSpec(FSSpec *fSpec);
static Boolean ShouldHiliteSelect(FSSpec *fSpec);
/* typedefs */
typedef struct {
StandardFileReply *replyPtr;
FSSpec oldSelection;
} SFData, *SFDataPtr;
/* constants */
#define kSelectItem 10
#define kSFDlg 129
#define kCanSelectDesktop true
#define kSelectStrRsrc 128
#define kDefaultSelectString "¥pSelect"
#define kDeskStrRsrc 129
#define kDefaultDeskString "¥pDesktop"
#define kSelectKey 's'
/* globals */
FSSpec gDeskFolderSpec;
Str255 gSelectString;
Str255 gDesktopFName;
/*
* Usage:
* FSSpec fSpec;
* Boolean good;
*
* extern Boolean SFGetFolder(FSSpec *fSpec);
* good = SFGetFolder(&fSpec);
*/
/* initialize managers */
static void InitStuff(void)
{
Handle strHndl;
strHndl = Get1Resource('STR ',kSelectStrRsrc);
if (ResError()!=noErr || !strHndl || !*strHndl)
BlockMove(kDefaultSelectString,gSelectString,kDefaultSelectString[0]+1);
else
{
BlockMove(*strHndl,&gSelectString,(long)((unsigned char *)(*strHndl)[0]+1));
ReleaseResource(strHndl);
}
strHndl = Get1Resource('STR ',kDeskStrRsrc);
if (ResError()!=noErr || !strHndl || !*strHndl)
BlockMove(kDefaultDeskString,gDesktopFName,kDefaultSelectString[0]+1);
else
{
BlockMove(*strHndl,&gDesktopFName,(long)((unsigned char *)(*strHndl)[0]+1));
ReleaseResource(strHndl);
}
}
/* do getfile */
Boolean SFGetFolder(FSSpec *fSpec)
{
Point where = {-1,-1};
StandardFileReply sfReply;
SFData sfUserData;
OSErr err;
Boolean targetIsFolder,
wasAliased;
#if GENERATINGCFM || USESROUTINEDESCRIPTORS
CreateRoutineDescriptor(uppFileFilterYDProcInfo, FilterAllFiles);
CreateRoutineDescriptor(uppDlgHookYDProcInfo, MyDlgHook);
CreateRoutineDescriptor(uppModalFilterYDProcInfo, MyModalFilter);
#endif
InitStuff();
/* initialize user data area */
sfUserData.replyPtr = &sfReply;
sfUserData.oldSelection.vRefNum = -9999; /* init to ridiculous value */
CustomGetFile(
(FileFilterYDUPP)GetRoutineAddress(FilterAllFiles),
-1,nil,
&sfReply,
kSFDlg,
where,
(DlgHookYDUPP)GetRoutineAddress(MyDlgHook),
(ModalFilterYDUPP)GetRoutineAddress(MyModalFilter),
nil,nil,&sfUserData);
if (sfReply.sfGood)
{
MakeCanonFSSpec(&sfReply.sfFile); /* spd, August 29, 1995 */
err = ResolveAliasFile(&sfReply.sfFile,true,&targetIsFolder,&wasAliased);
if (err!=noErr)
return false;
}
err = FSMakeFSSpec(sfReply.sfFile.vRefNum,sfReply.sfFile.parID,sfReply.sfFile.name,fSpec);
if (err!=noErr)
return false;
return sfReply.sfGood;
}
/* this dialog hook checks the contents of the additional edit fields
when the user selects a file. The focus of the dialog is changed if one
of the fields is out of range.
*/
static pascal short MyDlgHook(short item,DialogPtr theDlg,Ptr userData)
{
SFDataPtr sfUserData;
FSSpec curSpec;
OSType refCon;
refCon = GetWRefCon(theDlg);
if (refCon!=sfMainDialogRefCon)
return item;
sfUserData = (SFDataPtr) userData;
if (item==sfHookFirstCall || item==sfHookLastCall)
return item;
if (item==sfItemVolumeUser) {
sfUserData->replyPtr->sfFile.name[0] = '¥0';
sfUserData->replyPtr->sfFile.parID = 2;
sfUserData->replyPtr->sfIsFolder = false;
sfUserData->replyPtr->sfIsVolume = false;
sfUserData->replyPtr->sfFlags = 0;
item = sfHookChangeSelection;
}
if (!SameFile(&sfUserData->replyPtr->sfFile,&sfUserData->oldSelection)) {
BlockMove(&sfUserData->replyPtr->sfFile,&curSpec,sizeof(FSSpec));
MakeCanonFSSpec(&curSpec);
if (curSpec.vRefNum!=sfUserData->oldSelection.vRefNum)
GetDeskFolderSpec(&gDeskFolderSpec,curSpec.vRefNum);
SetSelectButtonName(curSpec.name,ShouldHiliteSelect(&curSpec),theDlg);
BlockMove(&sfUserData->replyPtr->sfFile,&sfUserData->oldSelection,sizeof(FSSpec));
}
if (item==kSelectItem)
item = sfItemOpenButton;
return item;
}
static pascal Boolean MyModalFilter(DialogPtr theDlg,EventRecord *ev,short *itemHit,Ptr myData)
{
#pragma unused(myData)
Boolean evHandled;
char keyPressed;
OSType refCon;
refCon = GetWRefCon(theDlg);
if (refCon!=sfMainDialogRefCon)
return false;
evHandled = false;
switch (ev->what)
{
case keyDown:
case autoKey:
keyPressed = ev->message & charCodeMask;
if ((ev->modifiers & cmdKey) != 0)
{
switch (keyPressed)
{
case kSelectKey:
HitButton(theDlg,kSelectItem);
*itemHit = kSelectItem;
evHandled = true;
break;
}
}
break;
}
return evHandled;
}
static void HitButton(DialogPtr theDlg,short item)
{
short iType;
ControlHandle iHndl;
Rect iRect;
long fTicks;
GetDialogItem(theDlg,item,&iType,(Handle *)&iHndl,&iRect);
#ifndef THINK_C
HiliteControl(iHndl, kControlButtonPart);
#else
HiliteControl(iHndl, inButton);
#endif
Delay(5,&fTicks);
HiliteControl(iHndl,0);
}
static pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr)
{
#pragma unused(myDataPtr)
if (pb->hFileInfo.ioFlAttrib & (1<<4)) /* file is a directory */
return false;
return true;
}
static void SetSelectButtonName(StringPtr selName,Boolean hilited,DialogPtr theDlg)
{
short iType;
Handle iHndl;
Rect iRect;
Str255 storeName,tempLenStr,tempSelName;
short btnWidth;
BlockMove(selName,tempSelName,selName[0]+1);
GetDialogItem(theDlg,kSelectItem,&iType,&iHndl,&iRect);
/* truncate select name to fit in button */
btnWidth = iRect.right - iRect.left;
BlockMove(gSelectString,tempLenStr,gSelectString[0]+1);
PStrCat(tempLenStr, "¥p メモ ");
btnWidth -= StringWidth(tempLenStr);
TruncString(btnWidth,tempSelName,smTruncMiddle);
BlockMove(gSelectString,storeName,gSelectString[0]+1);
PStrCat( storeName, "¥p メ");
PStrCat( storeName, tempSelName);
PStrCat( storeName, "¥pモ");
SetControlTitle((ControlHandle)iHndl,storeName);
SetDialogItem(theDlg,kSelectItem,iType,iHndl,&iRect);
if (hilited)
HiliteControl((ControlHandle)iHndl,0);
else
HiliteControl((ControlHandle)iHndl,255);
}
static Boolean SameFile(FSSpec *file1,FSSpec *file2)
{
if (file1->vRefNum != file2->vRefNum)
return false;
if (file1->parID != file2->parID)
return false;
if (!EqualString(file1->name,file2->name,false,true))
return false;
return true;
}
static OSErr GetDeskFolderSpec(FSSpec *fSpec,short vRefNum)
{
OSErr err;
fSpec->name[0] = '¥0';
err = FindFolder(vRefNum,kDesktopFolderType,kDontCreateFolder,
&fSpec->vRefNum,&fSpec->parID);
if (err!=noErr)
return err;
return MakeCanonFSSpec(fSpec);
}
static Boolean ShouldHiliteSelect(FSSpec *fSpec)
{
if (SameFile(fSpec,&gDeskFolderSpec)) {
BlockMove(gDesktopFName,fSpec->name,gDesktopFName[0]+1);
return kCanSelectDesktop;
}
else
return true;
}
static OSErr MakeCanonFSSpec(FSSpec *fSpec)
{
DirInfo infoPB;
OSErr err;
if (fSpec->name[0] != '¥0')
return noErr;
infoPB.ioNamePtr = fSpec->name;
infoPB.ioVRefNum = fSpec->vRefNum;
infoPB.ioDrDirID = fSpec->parID;
infoPB.ioFDirIndex = -1;
err = PBGetCatInfoSync((CInfoPBPtr)&infoPB);
fSpec->parID = infoPB.ioDrParID;
return err;
}